#pragma once

#include "vrdatacore_global.h"
#include <osg\Vec2>
#include <QVector>
#include "drawable.h"
#include <osg\ref_ptr>
#include <osg\Camera>
#include "selecteffect.h"
#include "templateclass.h"
#include "datatypedefine.h"
#include <osgUtil\LineSegmentIntersector>
#include "commonshape.h"
#include "viewer.h"

namespace osg
{
	class Node;
	class Group;
}

namespace CoreBase
{
	class Scene;
}

namespace VrDataCore
{
	class VRDATACORE_EXPORT PickManager
	{
	public:
		static PickManager& GetInstance();
		
		void initPickManager(CoreBase::Viewer* view,CoreBase::Scene* scene);
		void changeScene(CoreBase::Scene*);
		void clearAllPickObjects();
		void setSelectRectBase(const osg::Vec3& base);
		void upDateSelectRect(int w, int l);
		void upDateSelectRect(const osg::Vec3& newpoint);
		void pickObjects(const osg::Vec2 &mouseend,bool andbase,bool addpick,unsigned int traversalmask,
			const QString& classname,QVector<CoreBase::Drawable*> selectenabledrawables = QVector<CoreBase::Drawable*>(0));
		void pickObjects(const osg::Vec2 &mousepos,bool addpick,unsigned int traversalmask,
			const QString& classname,QVector<CoreBase::Drawable*> selectenabledrawables = QVector<CoreBase::Drawable*>(0));
		void pickObjects(const osg::Vec2 &mousestart,const osg::Vec2 &mouseend,unsigned int traversalmask,
			const QString& classname,bool addpick = false,QVector<CoreBase::Drawable*> selectenabledrawables = QVector<CoreBase::Drawable*>(0));
		QVector<CoreBase::ActorBase*> pickObjectsNoUpdate(const osg::Vec2 &mousepos,unsigned int traversalmask,
			const QString& classname,QVector<CoreBase::Drawable*> selectenabledrawables = QVector<CoreBase::Drawable*>(0));
		template<typename T>
		QVector<T> pickObjectNoUpdate(const osg::Vec2 &mousepos,unsigned int traversalmask)
		{
			QVector<T> v;
			bool findsuccess = false;
			osgUtil::LineSegmentIntersector::Intersections hitlist;
			dynamic_cast<osgViewer::View*>(_currentView)->computeIntersections(mousepos.x(), mousepos.y(),
					hitlist, traversalmask);
			for (std::multiset<osgUtil::LineSegmentIntersector::Intersection>::const_iterator hitItr = hitlist.begin();
				hitItr != hitlist.end();++hitItr)
			{
				for (osg::NodePath::const_reverse_iterator nodeItr = hitItr->nodePath.rbegin();
					nodeItr != hitItr->nodePath.rend();
					++nodeItr)
				{
					if (dynamic_cast<T>(*nodeItr)!=NULL)
					{
						v.push_back(dynamic_cast<T>(*nodeItr));
						findsuccess = true;
						break;
					}
					if(findsuccess)
						break;
				}
				if(findsuccess)
					break;
			}
			return v;
		}
		QVector<CoreBase::Drawable*> getPickObjects();
		QVector<CoreBase::ActorBase*> getPickActorObjects();
		CoreBase::Drawable* getSelectionRectNode();
		template<typename T>
		void registerPickObjectChangeEvent(const QString& key,void (T::*function)(),T* obj)
		{
			osg::ref_ptr<FuncBase> newfunc = new VoidFunc<void,T>(function,obj);
			_funcMap.insert(key,newfunc);
		}
		void viewResize(const int w,const int h);
		void addPickObjects(QVector<CoreBase::ActorBase*> objectvector);
		QVector<osgUtil::LineSegmentIntersector::Intersection> getPreviousLineSegmentIntersectorIntersection();
		void getLineSegmentIntersectResult(const osg::Vec3& start,const osg::Vec3& end,osg::Vec3& point,osg::Vec3& normal
			,unsigned int traversalmask,osg::Node* target = NULL);
		void getLineSegmentIntersectResultInCollisionLayer(const osg::Vec3& start,const osg::Vec3& end,osg::Vec3& point,osg::Vec3& normal);
	private:
		void showSelectActors();
		void callRegisterFun();
		PickManager();
		~PickManager();
	private:
		static PickManager*											_manager;
		CoreBase::Scene*												_currentScene;
		CoreBase::Viewer*												_currentView;
		QVector<CoreBase::Drawable*>									_drawableVector;
		osg::ref_ptr<CoreBase::LineRectShape>							_lineRectShape;
		osg::Vec3														_rectBase;
		QMap<CoreBase::ActorBase*,osg::ref_ptr<SelectEffect>>				_boundingBoxEffectMap;
		QMap<QString,osg::ref_ptr<FuncBase>>								_funcMap;
		QVector<osgUtil::LineSegmentIntersector::Intersection>				_intersectionVector;
		unsigned int													_traversalMask;
	};
}